frida for windows
grandfrida for windows
参考
Frida-Windows 夏洛魂的个人博客
JavaScript API | Frida • A world-class dynamic instrumentation toolkit
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include<stdio.h> #include<stdint.h>
int add(int a,int b){ return a+b; }
int main(){ int a=6; int b=7; printf("%d",add(a,b)); }
|
很简单的测试脚本 挨个把官方文档的api都试一试

搞一个开发环境
1 2 3
| git clone https://github.com/oleavr/frida-agent-example.git cd frida-agent-example/ npm install
|
网速慢就直接
1
| git config --global http.proxy http://127.0.0.1:7897
|

Process


先给出常见类的几个基础的属性
获取id
1
| frida -f test.exe -l .\exp\hook.js
|
1 2
| var baseaddres =Process.id console.log(baseaddres)
|

当面对多线程的时候即可使用
1 2
| Process.getCurrentThreadId() Process.enumerateThreads()
|
进行查看
获取地址
1 2 3 4 5 6 7 8
| var baseaddress = Process.mainModule; console.log("Main module:", baseaddress); console.log("Base address:", baseaddress.base); console.log("Name:", baseaddress.name); console.log("Path:", baseaddress.path); console.log("Size:", baseaddress.size);
|

获取到目前加载的模块
1 2 3 4 5 6 7 8 9 10
| // 获取目标模块的符号表 var symbols = Process.enumerateModules()
// 遍历并打印符号信息 symbols.forEach(symbols =>{ console.log('Name:', symbols.name, 'Type:', symbols.size, 'Module:', symbols.base, 'Address:', symbols.path) })
|

获取模块地址
Process.findModuleByAddress(address)
Process.getModuleByAddress(address)
Process.findModuleByName(name)
Process.getModuleByName(name)
其实功能都差不多 就是弹不弹异常的区别 get失败返回null find失败直接异常
1 2 3 4 5 6 7 8 9 10
| // 获取目标模块的符号表 var symbols = Process.findModuleByAddress(0x7ffedc230000) console.log(symbols) // 遍历并打印符号信息
console.log('Name:', symbols.name, 'Type:', symbols.size, 'Module:', symbols.base, 'Address:', symbols.path);
|
获取module内存的信息
1 2 3 4 5
| var Moduleaddres = Process.findModuleByName("msvcrt.dll")
var address=Process.findRangeByAddress(ptr(Moduleaddres.base))
console.log(address.base,address.size,address.file,address.protection)
|

Module
hook函数
1 2 3 4 5 6 7 8 9 10
| var addres =Module.findBaseAddress("test.exe").add(0x1550) console.log(addres) Interceptor.attach(addres,{ onEnter(args){ console.log("yes") }, onLeave(reda){ console.log(reda) } })
|

获取到参数 修改返回值
1 2 3 4 5 6 7 8 9 10
| var addres =Module.findBaseAddress("test.exe").add(0x1550) console.log(addres) Interceptor.attach(addres,{ onEnter(args){ console.log(args[0],args[1]) }, onLeave(reda){ reda.replace(1000) } })
|

获取到导入module信息 返回列表
1 2 3 4 5 6 7 8 9 10
| // 获取目标模块的导入函数列表 const imports = Module.enumerateImports("test.exe");
// 遍历并打印所有导入函数 imports.forEach(imp => { console.log('Name:', imp.name, 'Type:', imp.type, 'Module:', imp.module, 'Address:', imp.address); });
|

获取导出信息 返回列表
1 2 3 4 5 6 7 8 9
| // 获取目标模块的导出函数列表 const exports = Module.enumerateExports("msvcrt.dll"); console.log("yes") // 遍历并打印所有导出函数 exports.forEach(exp => { console.log('Name:', exp.name, 'Type:', exp.type, 'Address:', exp.address); });
|

获取目标模块的符号表
1 2 3 4 5 6 7 8 9 10
| // 获取目标模块的符号表 const symbols = Module.enumerateSymbols("msvcrt.dll");
// 遍历并打印符号信息 symbols.forEach(sym => { console.log('Name:', sym.name, 'Type:', sym.type, 'Address:', sym.address, 'Size:', sym.size); });
|

字符串读取api
API |
说明 |
{NativePointer}.readCString() |
读取C风格字符串 |
{NativePointer}.readAnsiString() |
读取Ansi字符串 |
{NativePointer}.readUtf8String() |
读取UTF8字符串 |
{NativePointer}.readUtf16String() |
读取UTF16字符串 |
Frida提供的读取数值API
API |
说明 |
{}.readInt() |
从给定地址读取整数 |
{}.readUInt() |
从给定地址读取无符号整数 |
{}.readS8() |
从指定地址读取带符号的8位、16位、32位或64位整数 |
{}.readShort() |
从给定地址读取短整数 |
{}.readFloat() |
从给定地址读取浮点数 |
{}.readDouble() |
从给定地址读取双浮点数 |
{}.readLong() |
从给定地址读取长数字 |
{}.readULong() |
从给定地址读取无符号长数字 |
{}.readUShort() |
从给定地址读取无符号短数 |
{}.readUS8() |
从给定地址读取无符号整数 |
Frida提供的数值写入API
API |
说明 |
{}.writeInt() |
向给定地址写入整数 |
{}.writeUInt() |
向给定地址写入无符号整数 |
{}.writeS8() |
向给定地址写入带符号的8位、16位、32位或64位整数 |
{}.writeShort() |
向给定地址写入短整数 |
{}.writeFloat() |
向给定地址写入浮点数 |
{}.writeDouble() |
向给定地址写入双浮点数 |
{}.writeLong() |
向给定地址写入长数字 |
{}.writeULong() |
向给定地址写入无符号长数字 |
{}.writeUShort() |
向给定地址写入无符号短数 |
{}.writeUS8() |
向给定地址写入无符号整数 |
Hexdump
1 2 3 4
| var baseaddres = Process.mainModule console.log(baseaddres.base)
console.log(hexdump(baseaddres.base, {offset: 0,length: 16,header: false,ansi: true}))
|
创建本地函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| new NativeFunction(address, returnType, argTypes[, abi])
//TYPES 可选如下: void pointer int uint long ulong char uchar size_t ssize_t float double int8 uint8 int16 uint16 int32 uint32 int64 uint64 bool
//ABIS 可选如下: default Windows 32-bit: sysv stdcall thiscall fastcall mscdecl Windows 64-bit: win64 UNIX x86: sysv unix64 UNIX ARM: sysv vfp
|
1 2 3 4 5 6
| var baseaddres =Process.mainModule console.log(baseaddres.base)
var myfunction =new NativeFunction(baseaddres.base.add(0x1550),"int",["int","int"])
console.log(myfunction(1000,1200))
|

函数替换
使用nterceptor.replace()进行操作
1 2 3 4 5 6
| var baseaddres =Process.mainModule console.log(baseaddres.base)
Interceptor.replace(baseaddres.base.add(0x1550),new NativeCallback(function(a,b){ return a*b },'int', ['int', 'int']))
|

内存扫描
1 2 3
| //pattern的格式为由空格分隔的16进制字符串 Memory.scan(address, size, pattern, callbacks) Memory.scanSync(address, size, pattern)
|
寄存器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var addPtr = Process.mainModule.base.add(0x16F8F0)
Interceptor.attach(addPtr, { onEnter (args) { // console.log('args0:' + args[0]); // console.log('args1:' + args[1]);
console.log('args1:' + this.context.rcx.toInt32()); console.log('args2:' + this.context.rdx.toInt32()); } });
//修改寄存器 // Memory.patchCode(addPtr, Process.pointerSize, function (code) { // const cw = new X86Writer(code, { pc: addPtr }); // cw.putMovRegU32('eax', 1234); // cw.putRet(); // cw.flush(); // });
|